package cc.fs.zhihuapp.utils.SmbUtils;

import android.util.Log;

import java.io.InputStream;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import jcifs.smb.SmbFile;

/**
 * Created by fostion on 2015/11/21.
 * smb代理实现android手机建立服务器转发信息
 */
public class SmbProxy extends NanoHTTPD {

    private static final String host = "127.0.0.1";
    private static final int port = 4455;
    private final String TAG = "--SmbProxy--";
    private final String PROXY = "/stream/";

    public void e(String msg) {
        Log.e(TAG, msg);
    }

    public SmbProxy() {
        super(host, port);
        setAsyncRunner(new ThreadPoolRunner());
    }

    public String getFormatUrl(String url){
        return String.format("http://%s:%d/stream/%s",host,port,url);
    }

    @Override
    public Response serve(IHTTPSession session) {
        //接受发过来的请求，并返回结果
        e("服务器接受到信息" + session.getUri());
        String uri = session.getUri();
        uri = uri.substring(PROXY.length());
        return handleRequest(uri, session);
    }

    /**
     * 处理发送过来的请求
     */
    private Response handleRequest(String uri, IHTTPSession session) {
        Response response = null;
        SmbFile smbfile = null;
        try {
            uri = "smb://" + uri;
            e("请求的smb连接是："+ uri);
            smbfile = new SmbFile(uri);
            if (smbfile == null)
                return null;
        } catch (MalformedURLException e) {
            e("smb地址有误，无法连接局域网中的服务器");
        }

        try {
            //获取文件类型
            String mimeType = smbfile.getContentType();
            if (mimeType == null) mimeType = uri.substring(uri.lastIndexOf("."));
            //获取返回内容
            response = serverFile(session.getHeaders(), smbfile, mimeType);
        } catch (Exception e) {
            e.printStackTrace();
            e("返回内容时出现错误！");
        }
        return response;
    }

    public Response serverFile(Map<String, String> header, SmbFile file, String mime) {
        boolean success = false;
        Response response = null;
        InputStream fis = null;

        try {
            // Calculate etag
            String etag = Integer.toHexString((file.getCanonicalPath() + file.lastModified() + "" + file.length()).hashCode());

            //支持跳动播放
            long startFrom = 0;
            long endAt = -1;
            String range = header.get("range");
            if(range != null){
                if(range.startsWith("bytes=")){
                    range = range.substring("bytes=".length());
                    int minus = range.indexOf("-");
                    try{
                        startFrom = Long.parseLong(range.substring(0,minus));
                        endAt = Long.parseLong(range.substring(minus+1));
                    } catch (Exception e){
                        e("获取播放出错了");
                    }
                }
            }

            //如果服务器文件未改变，服务器发送客户端丢失的部分，否则发送整个实体
            String ifRange = header.get("if-range");
            boolean headerIfRangeMissingOrMatching  = (ifRange == null || etag.equals(ifRange));

            //如果服务器未改变返回304代码
            String ifNoneMatch = header.get("if-none-match");
            boolean headerIfNoneMatchPresentAndMatching = ifNoneMatch != null && (ifNoneMatch.equals("*") || ifNoneMatch.equals(etag));

            //开始返回文件实体
            long fileLen = file.length();
            fis = file.getInputStream();

            //文件未改变
            if (headerIfRangeMissingOrMatching && range != null && startFrom >= 0 && startFrom < fileLen) {
                if (headerIfNoneMatchPresentAndMatching) {
                    response = newFixedLengthResponse(Response.Status.NOT_MODIFIED, mime, "");
                    response.addHeader("ETag", etag);
                } else {
                    if (endAt < 0) {
                        endAt = fileLen - 1;
                    }
                    long newLen = endAt - startFrom + 1;
                    if (newLen < 0) {
                        newLen = 0;
                    }

                    //跳过部分流 todo 注释
//                    ByteStreams.skipFully(fis, startFrom);
                    response = newFixedLengthResponse(Response.Status.PARTIAL_CONTENT, mime, fis, newLen);
                    response.addHeader("Accept-Ranges", "bytes");
                    response.addHeader("Content-Length", "" + newLen);
                    response.addHeader("Content-Range", "bytes " + startFrom + "-" + endAt + "/" + fileLen);
                    response.addHeader("ETag", etag);
                }
            } else {
                if (headerIfRangeMissingOrMatching && range != null && startFrom >= fileLen) {
                    response = newFixedLengthResponse(Response.Status.RANGE_NOT_SATISFIABLE, NanoHTTPD.MIME_PLAINTEXT, "");
                    response.addHeader("Content-Range", "bytes */" + fileLen);
                    response.addHeader("ETag", etag);
                } else if (range == null && headerIfNoneMatchPresentAndMatching) {
                    response = newFixedLengthResponse(Response.Status.NOT_MODIFIED, mime, "");
                    response.addHeader("ETag", etag);
                } else if (!headerIfRangeMissingOrMatching && headerIfNoneMatchPresentAndMatching) {
                    response = newFixedLengthResponse(Response.Status.NOT_MODIFIED, mime, "");
                    response.addHeader("ETag", etag);
                } else {
                    // 返回文件
                    response = newFixedLengthResponse(Response.Status.OK, mime, fis, fileLen);
                    response.addHeader("Content-Length", Long.toString(fileLen));
                    response.addHeader("ETag", etag);
                }
            }
            e("从服务器获取成功");
            success = true;
        } catch (Exception e) {
            e.printStackTrace();
            e("从服务器读取中出现异常");
            response = getForbiddenResponse();
        } finally {
            if (!success && fis != null) {
                try{
                    fis.close();
                } catch (Exception e){
                    e("输出流关闭失败");
                }
            }
        }
        return response;
    }

    protected Response getForbiddenResponse() {
        return newFixedLengthResponse(Response.Status.FORBIDDEN, MIME_PLAINTEXT, "Forbidden");
    }

    public void startProxy() {
        try {
            start();
            e("服务器开启成功");
        } catch (Exception e) {
            e.printStackTrace();
            e("服务器开启失败");
        }
    }

    public void stopProxy() {
        try {
            stop();
            e("代理关闭成功");
        } catch (Exception e) {
            e.printStackTrace();
            e("代理关闭失败");
        }
    }


    public static class ThreadPoolRunner implements AsyncRunner {
        private final ExecutorService mExecutor = Executors.newCachedThreadPool();
        private final List<ClientHandler> running = Collections.synchronizedList(new ArrayList<ClientHandler>());

        @Override
        public void closeAll() {
            // copy of the list for concurrency
            mExecutor.shutdown();
            //todo 注释
//            for (ClientHandler clientHandler : Lists.newArrayList(running)) {
//                clientHandler.close();
//            }
        }

        @Override
        public void closed(ClientHandler clientHandler) {
            running.remove(clientHandler);
        }

        @Override
        public void exec(ClientHandler clientHandler) {
            running.add(clientHandler);
            mExecutor.submit(clientHandler);
        }
    }
}
